|
fawaz2000 مبرمج محترف
تاريخ التسجيل » Nov
2001
البلد » اليمن
- صنعاء
عدد
المشاركات » 297
بمعدل » 0.43 مشاركة لكل يوم |
بسم الله أخواني الكرام مواصلة
لدروس السابقة سوف نتعرف عن الطريقة الثانية التوليد (أو إنتاج )
الحدث : Mouse_Exit و Mouse_Enter :
الطريقة الثانية
باستخدام أداة Timer : وبما أننا نستخدم هذه الأداة فهناك
عيب كبير لهذه الطريقة هوا استخدام الأداة (Timer) حيث أن الأداة
Timer تضل تفحص مادام البرنامج شغال . لعمل هذه الطريقة نتبع
الأتي :
أولاً نضع الأداة Timer على النافذة التصميم
UserControl ثم نضع خاصية InterVal ما بين 1 إلى 50 حيث من هذه
الأرقام تكون الأداة سريعة وقادرة على الفحص وتتبع حركات الماوس
بسرعة . مثلاُ لنختار الرقم 1 للخاصية .
فكرة هذه
الطريقة قريبة من الطريقة الأول حيث : أولا : سنقوم بالحصول
على موقع مؤشر الماوس الحالي للمستوى العمودي (y) والمستوى
الأفقي (x) . ثانياً : سنقوم بفحص هذه المواقع على مستوى
النافذة . أي عندما يمر الماوس على الزر . ثالثا : نضع شرط
يقوم بتوضيح موقع الماوس هل هوا خارج أم داخل الزر .
في
البداية : 1- الحصول على موقع الماوس : هناك دالة Api
تقوم بإرجاع قيم توضح أبعاد موقع مؤشر الماوس . وهذه الدالة
هي : GetCursorPos صيغة الدالة :
code:
Private Declare Function GetCursorPos Lib "user32" _
(lpPoint As POINTAPI) As Long | | والملاحظ هنا أن هذه الدالة تأخذ
باراميتر واحد هوا : lpPoint : يرجع قيمة تحدد موقع المشيرة
بإحداثيات الشاشة . نوع البيانات للبااراميتر هوا: POINTAPI :
وهي البنية التي سوف تحمل موقع المشيرة بإحداثيات الشاشة . (x,y)
. حيث هذه البيانات هي :
code:
Private Type POINTAPI
x As Long
y As Long
End Type | |
ويفضل وضعها قبل الدالة
GetCursorPos . مثل :
code:
Private Type POINTAPI
x As Long
y As Long
End Type
Private Declare Function GetCursorPos Lib "user32" _
(lpPoint As POINTAPI) As Long | | حيث توضع طبعاً هذه الدوال في قسم
التصريحات العامة General . القيمة المعادة : غير صفرية في
خالة النجاح صفرية في حال الفشل . الدالة الثانية : وهي
التي تحدد أو ترجع القيم التي تمثل مقبض النوافذ عندما يكون x,y
للمشيرة (مؤشر الماوس) على النافذة (الزر) . وهذه الدالة هي :
WindowFromPoint : صيغة الدالة :
code:
Private Declare Function WindowFromPoint Lib "user32" _
(ByVal xPoint As Long, ByVal yPoint As Long) As Long | | حيث باراميترات هذه الدالة
: xPoint : قيمة تمثل موقع المشيرة بالنسبة للمستوى الأفقي
للشاشة (x) . yPoint : قيمة تمثل موقع المشيرة بالنسبة
للمستوى العمودي للشاشة (y). وهذه الباراميترات سوف تأخذ
القيم من نوع البيانات POINTAPI . القيم المعادة : مقبض
النافذة الواقعة تحت المشيرة , صفرية في حال الفشل
.
ملاحظة : هذه الدوال يمكنك الحصول عليها من البرنامج
API Text Viewer المرفق مع فيجول بيسك . الآن بعد أن حددنا
موقع الماوس ثم حددنا موقع الإحداثيات عندما يكون مؤشر الماوس
على الزر . سوف نبدأ على النحو التالي : في أداة Timer
: سنقوم بتعريف متغير نوع البيانات له هي POINTAPI , و
بالتالي هذا المتغير يحمل قيم x,y ثم سنعطي هذا المتغير
للدالة GetCursorPos والتي ستقوم بوضع القيم الحالية للمشيرة في
المتغير الذي يحمل x,y . وبعد أن حصل المتغير على القيم سوف
نعطي قيم المتغير للإحداثيات للدالة WindowFromPoint والتي سترجع
لنا قيمة مبنية على الإحداثيات على النافذة أي أن القيمة المعادة
من الدالة فقط قيم عند خروج الماوس وقيم عن دخول الماوس على
النافذة . وبالتالي سنفحص القيم فقط عندما يكون المشيرة على
النافذة (الزر) وليس إحداثيات الشاشة ككل . كما يلي
:
code:
Private Sub Timer1_Timer()
Dim Points As POINTAPI
GetCursorPos Points
WindowFromPoint Points.x, Points.y
End Sub | |
ملاحظة : الدالة
WindowFromPoint : ترجع قيمة مشابهة لقيمة مقبض النافذة فمثلاً
. لو كان مقبض النافذة هو 2000 فإن الدالة ترجع قيمة عندما
يكون الماوس فوق النافذة (الزر) 2000 أي أن عمل الدالة
WindowFromPoint هوا الحصول على مقبض نافذة ما . (تعيد مقبض
النافذة التي تحتوي على النقاط المحددة . تهمل النوافذ المخفية
والشفافة . وهذه الملاحظة ستقودنا إلى شرط مهم جداً وهوا إذا
كانت القيمة الناتجة للدالة مساوية لمقبض النافذة فإن الماوس
داخل الزر . وعكس ذلك فإن الماوس( أو المؤشر أو المشيرة ) خارج
الزر .
قد يتساءل شخص ما هوا مقبض النافذة hWnd.
:
قبل أن أوضح مفهوم المقبض سوف أضع سؤال . كيف يتعامل
وندوز مع النوافذ .
يتعامل نضام التشغيل Windows مع
النوافذ عن طريق الرسائل . حيث لو كانت لدي نافذة أريد أن أغلقها
فعند النقر على زر الإغلاق ينتقل الأمر إلى المعالج . ثم بعد
معالجة الأمر يعود ناتج المعالجة إلى النافذة ثم يقوم بإغلاقها .
لاحظ كلمة ينتقل الأمر إلى المعالج ثم يعود , فكيف يعود ناتج
الأمر إلى نفس النافذة التي أريد أن أقوم بإغلاقها , يعني لماذا
لا يخطى ناتج الأمر ويذهب إلى نافذة أخرى ويغلقها . لتفادي هذه
المشكلة التي تعبر أكبير عيب قد يواجه نضام التشغيل في التحكم في
النوافذ . أبتكر ما يسمي مقبض النوافذ هذ 1ذذذ6 ا المقبض يعطي كل
نافذة رقم معين (32Bit) تقريباُ حيث لكل نافذة يتم فتحها تعطى
رقم مختلف عن أرقام النوافذ الأخرى تسمى هذه العملة بالمقبض hWnd
. فعند معالجة أمر يمرر على أساس رقم النافذة ثم يعود على أساس
رقم النافذة وبالتالي يستطيع نضام التشغيل معرفة أي نافذة أرادت
أمر معين ثم يرجع لها ناتج هذه العملية بمعرفة مقبضها (رقمها
hWnd ) , تملك كل نافذة هذا الأمر (hWnd) وفي النوافذ يستخدم
لإرجاء قيمة تبين كم الرقم الذي أعطي للنافذة .
عناصر
التحكم ActiveX : تظهر بعض عناصر التحكم ActiveX وتعمل كعناصر
تحكم عادية : مثل صناديق النص وأزر الأمر وغير من الأدوات .
وتملك هذه الأدوات خاصية تسمي hWnd تعيد هذه الخاصة كما ذكرت رقم
النافذة التي تم إعطائها إياه من نضام التشغيل . لآن عناصر
التحكم ActiveX هي عبارة عن نافذة والنافذة تمتلك هذه الخاصية .
ملخص : المقبض hWnd : هو عبارة عن قيمة تبين
القيمة الحالية التي أعطاها نضام التشغيل للنافذة كي يتمكن من
معالجة أوامر النافذة عن طريق هذا الرقم . قام الهكرز
بالاستفادة من العملية في تتبع الرسائل التي ترسل من النافذة
وتعود إليها فقامو بتعديل هذه الرسائل بحيث يرجع قيم غير القيم
المطلوبة . وليس هذا موضوعنا لذا لن أغوس في هذا المجال وهوا
هيكلية النوافذ وطرق التعامل معها .
بعد هذا التوضيح
الطفيف عرفنا ماذا يعني مقبض النافذة . لذا سنقوم بأخذ القيمة
الناتجة من الدالة WindowFromPoint ثم سنقوم بإعطائها لمتغير .
هذا المتغير يحمل قيمة تبين مقبض النوافذ فكلما مر الماوس على
كائن ستأخذ هذه الدالة مقبض هذا الكائن ونحن بدورنا سنعرف كم
قيمة المقبض المعطى للنافذة (للكائن أو الزر المصمم) عن طريقة
الخاصية التي يمثلها وهي hWnd .
ملاحظة هامة : عندما
تعطي متغير مقبض النافذة يجب أن تعلم أن هذا المقبض يتغير إلى
قيم غير ثابتة كلما شغلت أو قمت بإغلاق النافذة . عندما وضعت
القيمة الناتجة إلى متغير في المثال كان ذلك في أداة تايمر حيث
يتجدد المقبض إذا غير .
نعرف متغير ولنسمه hWndButton من
نوع Long هذا المتغير ستعطيه الدالة WindowFromPoint رقم
المقابض التي يمر عليها الماوس . بعد ذلك نقارن هل المقبض
المار عليه الآن الماوس يساوي مقبض الزر الذي نريده . كما يلي
:
code:
Private Sub Timer1_Timer()
Dim hWndButton As Long
Dim Points As POINTAPI
GetCursorPos Points
hWndButton = WindowFromPoint(Points.x, Points.y)
If hWndButton = hWnd Then
BackColor = vbred
ElseIf hWndButton <> hWnd Then
BackColor = vbYellow
End If
'Debug.Print "wHwnd = "; hWndButton
End Sub | | شرح الكود : بعد أن تضع قيمة
للخاصية Interval التابعة للـ Timer : عرفنا متغير hWndButton
من نوع Long . ثم عرفنا متغير أخر Points من نوع POINTAPI
والمعرفة بقيم x,y . ثم وضعنا المتغير الذي يحمل القيم ليأخذ
القيم التي عليها الماوس حاليا ُ والتي تعطيه القيم الدالة
GetCursorPos . بعد ذلك قمنا باستخراج المقابض للنوافذ
(الكائنات) التي يمر عليها الماوس ووضعنا القيمة التي تمثل
المقبض في المتغير hWndButton . بعد أن حصلنا على مقابض
النوافذ قمنا بمقارنه القيمة الناتجة من hWndButton مع مقبض
النافذة (الزر) hWnd . ملاحظة : يمثل hWnd قيمة مقبض
النافذة يمكنك كتابته على النحو : Usercontrol.hWnd فكلاهما صحيح
لأن مترجم فيجول بيسك إذا وجد خاصية مكتوبة دون أن تسند مثل hWnd
أو BackColor .... سيعتبرها تابعة للنافذة . نقوم بوضع الشرط
التالي : If hWndButton = hWnd Then هل المقبض ألي عليه
الماوس حالياُ يساوي مقبض نافذتنا فأن تحقق الشرط يكون الماوس
داخل الزر حسب ويغير لون الخلفية إلى الأحمر حسب السطر BackColor
= vbread وإن لم يتحقق الشرط يغير لون الخلفية إلى الأصفر
دالاً على خروج الماوس . أما السطر : 'Debug.Print "wHwnd
= "; hWndButton فليس له علاقة بالموضوع سوى توضيح يبين أرقام
المقابض التي يمر عليها الماوس . كذلك يبين استمرار الإداه
بالفحص مادام البرنامج شغال .
لذا أنصح وبشدة ترك هذه
الطريقة واستخدام الطريقة السابقة . لا أن هذه الطريقة تهدر
الذاكرة .
ملاحظة : عند ما يتم وضع الأداة على نافذة
Form لاحظ ارتجاج شريط عنوان فيجول بيسك أيضاً عند مرور الماوس
على الزر يبدأ بالتنفيذ والسبب كما ذكرت في الدروس السابقة أن
الأداة تبدأ العمل لحظة وضعها على النموذج . لذلك يمكنك توقيف
بعض المهام عن العمل عندما يكون البرنامج ككل تحت
التصميم. تقوم الخاصية التالية UserMode بالعمل التي نصل
إليها من خلال UserControl.Ambient.UserMode = True or
False حيث تستخدم هذه الطريقة لتوقيف عمل معين عندما يكون
البرنامج تحت التصميم . حيث : True: إذا كانت الأداة
مستخدمه من قبل المستخدم في زمن التشغيل run-time . False:
إذا كانت الأداة مستخدمة من قبل المستخدم لها في زمن التصميم
. يكفي أن نضع هذا الكود في الحدث Show لتوقيف الـTimer عندما
يكون في زمن التصميم .
كي نقوم بتوقيف عمل الكود المكتوب
في أداة Timer عندما يكون الزر في زمن التصميم للربنامج ككل من
قبل المستخدم . سوف أدعه تمرين للقراء . لذا قم بتتبع
الشرح ثم قم بتكون الكود خطوه خطوه مع الشرح وإن صادفتك مشاكل
انظر الكود التالي :
code:
Option Explicit
Private Type POINTAPI
x As Long
y As Long
End Type
Private Declare Function GetCursorPos Lib "user32" _
(lpPoint As POINTAPI) As Long
Private Declare Function WindowFromPoint Lib "user32" _
(ByVal xPoint As Long, ByVal yPoint As Long) As Long
Private Sub Timer1_Timer()
Dim hWndButton As Long
Dim Points As POINTAPI
'معرفة موقع الماوس
GetCursorPos Points
'معرفة مقبض النافذة الوقع عليه المؤشر
hWndButton = WindowFromPoint(Points.x, Points.y)
'إذا كان يساوي المقبض
If hWndButton = hWnd Then
BackColor = vbRed
ElseIf hWndButton <> hWnd Then
BackColor = vbYellow
End If
'يوضح السطر التالي مقابض النوافذ التي يمر بها الماوس
'سطر توضيحي فقط لذا قم بحذفه
Debug.Print "wHwnd = "; hWndButton
End Sub
Private Sub UserControl_Show()
Timer1.Enabled = UserControl.Ambient.UserMode
End Sub
| | لاحظ السطر التالي :
Timer1.Enabled = UserControl.Ambient.UserMode يعطي
Timer1.Enabled إذا كان في زمن التصميم False وفي زمن
التشغيل يعطيه True.
وإلى هذا الدرس عزيزي القارئ تكون
قادر على إنشاء كائنات عناصر تحكم لذا سوف أطلب من جميع متابعي
الدروس البدا بتصميم صندوق النص الخاص ببرنامج Sub7 حيث قد وضعته
في أحد الدروس ولكن لم ستم استكمال برمجته للأحداث لذا أريد من
من حاول أو صممه أن يضعه هنا : في الدرس القادم سوف أضع
الصندوق إن شاء الله ثم بعد ذلك سننتقل إلى برمجة متطورة قليلاُ
لإنتاج كائنات أكثر تفصيلاُ بعد أن أخذنا الأساسيات
.
أتمنا من جميع الإخوة الذين يملكون أمثلة مصممة أن
يضعوها هنا لتعم الفائدة . سوف أقوم بوضع بعض الكائنات التي تم
تصميها مع الكود في الدورس القادمة . إلى القاء في الدرس
القادم . قد يحمل هذا الدرس بعض الأخطاء لذا أتمنا توضيح
الخطأ إن وجد لعدم مراجعة الدرس . مثال مرفق :
لتنزيل الملف المرفق
أنقر الرابط التالي: vb.zip بلا مسؤلية على المنتدى إن كان
المرفق يحتوي على فيروسات أو وسائل
تجسس تم
تحميل هذا الملف 40 مرة.
__________________ الإيمان
يمان والحكمة يمانية
أخبر
المراقب عن هذا الرد | رقم
الـ IP | تحرير
التوقيع |